home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
mint104s.zoo
/
mint.src
/
unifs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-08
|
13KB
|
618 lines
/*
Copyright 1991,1992 Eric R. Smith.
Copyright 1992 Atari Corporation.
All rights reserved.
*/
/* a simple unified file system */
#include "mint.h"
extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys;
static long ARGS_ON_STACK uni_root P_((int drv, fcookie *fc));
static long ARGS_ON_STACK uni_lookup P_((fcookie *dir, const char *name, fcookie *fc));
static long ARGS_ON_STACK uni_getxattr P_((fcookie *fc, XATTR *xattr));
static long ARGS_ON_STACK uni_chattr P_((fcookie *fc, int attrib));
static long ARGS_ON_STACK uni_chown P_((fcookie *fc, int uid, int gid));
static long ARGS_ON_STACK uni_chmode P_((fcookie *fc, unsigned mode));
static long ARGS_ON_STACK uni_rmdir P_((fcookie *dir, const char *name));
static long ARGS_ON_STACK uni_remove P_((fcookie *dir, const char *name));
static long ARGS_ON_STACK uni_getname P_((fcookie *root, fcookie *dir,
char *pathname, int size));
static long ARGS_ON_STACK uni_rename P_((fcookie *olddir, char *oldname,
fcookie *newdir, const char *newname));
static long ARGS_ON_STACK uni_opendir P_((DIR *dirh, int flags));
static long ARGS_ON_STACK uni_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *));
static long ARGS_ON_STACK uni_rewinddir P_((DIR *dirh));
static long ARGS_ON_STACK uni_closedir P_((DIR *dirh));
static long ARGS_ON_STACK uni_pathconf P_((fcookie *dir, int which));
static long ARGS_ON_STACK uni_dfree P_((fcookie *dir, long *buf));
static DEVDRV * ARGS_ON_STACK uni_getdev P_((fcookie *fc, long *devsp));
static long ARGS_ON_STACK uni_symlink P_((fcookie *dir, const char *name, const char *to));
static long ARGS_ON_STACK uni_readlink P_((fcookie *fc, char *buf, int buflen));
FILESYS uni_filesys = {
(FILESYS *)0,
FS_LONGPATH,
uni_root,
uni_lookup, nocreat, uni_getdev, uni_getxattr,
uni_chattr, uni_chown, uni_chmode,
nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename,
uni_opendir, uni_readdir, uni_rewinddir, uni_closedir,
uni_pathconf, uni_dfree, nowritelabel, noreadlabel,
uni_symlink, uni_readlink, nohardlink, nofscntl, nodskchng
};
/*
* structure that holds files
* if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive:
* "dev" holds the appropriate BIOS device number, and
* "data" is meaningless
* if (mode & S_IFMT == S_IFLNK), then this is a symbolic link:
* "dev" holds the user id of the owner, and
* "data" points to the actual link data
*/
typedef struct unifile {
char name[NAME_MAX+1];
ushort mode;
ushort dev;
FILESYS *fs;
void *data;
struct unifile *next;
} UNIFILE;
static UNIFILE u_drvs[UNI_NUM_DRVS];
static UNIFILE *u_root = 0;
void
unifs_init()
{
UNIFILE *u = u_drvs;
int i;
u_root = u;
for (i = 0; i < UNI_NUM_DRVS; i++,u++) {
u->next = u+1;
u->mode = S_IFDIR|DEFAULT_DIRMODE;
u->dev = i;
if (i == PROCDRV) {
strcpy(u->name, "proc");
u->fs = &proc_filesys;
} else if (i == PIPEDRV) {
strcpy(u->name, "pipe");
u->fs = &pipe_filesys;
} else if (i == BIOSDRV) {
strcpy(u->name, "dev");
u->fs = &bios_filesys;
} else if (i == UNIDRV) {
(u-1)->next = u->next; /* skip this drive */
} else if (i == SHMDRV) {
strcpy(u->name, "shm");
u->fs = &shm_filesys;
} else {
u->name[0] = i + 'a';
u->name[1] = 0;
u->fs = 0;
}
}
--u; /* oops, we went too far */
u->next = 0;
}
static long ARGS_ON_STACK
uni_root(drv, fc)
int drv;
fcookie *fc;
{
if (drv == UNIDRV) {
fc->fs = &uni_filesys;
fc->dev = drv;
fc->index = 0L;
return 0;
}
fc->fs = 0;
return EINTRN;
}
static long ARGS_ON_STACK
uni_lookup(dir, name, fc)
fcookie *dir;
const char *name;
fcookie *fc;
{
UNIFILE *u;
long drvs;
FILESYS *fs;
fcookie *tmp;
extern long dosdrvs;
TRACE(("uni_lookup(%s)", name));
if (dir->index != 0) {
DEBUG(("uni_lookup: bad directory"));
return EPTHNF;
}
/* special case: an empty name in a directory means that directory */
/* so do "." and ".." */
if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) {
dup_cookie(fc, dir);
return 0;
}
drvs = drvmap() | dosdrvs | PSEUDODRVS;
/*
* OK, check the list of aliases and special directories
*/
for (u = u_root; u; u = u->next) {
if (!stricmp(name, u->name)) {
if ( (u->mode & S_IFMT) == S_IFDIR ) {
if (u->dev >= NUM_DRIVES) {
fs = u->fs;
return (*fs->root)(u->dev,fc);
}
if ((drvs & (1L << u->dev)) == 0)
return EPTHNF;
tmp = &curproc->root[u->dev];
if (!tmp->fs) { /* drive changed? */
changedrv(tmp->dev);
tmp = &curproc->root[u->dev];
if (!tmp->fs)
return EPTHNF;
}
dup_cookie(fc, tmp);
} else { /* a symbolic link */
fc->fs = &uni_filesys;
fc->dev = UNIDRV;
fc->index = (long)u;
}
return 0;
}
}
DEBUG(("uni_lookup: name (%s) not found", name));
return EFILNF;
}
static long ARGS_ON_STACK
uni_getxattr(fc, xattr)
fcookie *fc;
XATTR *xattr;
{
UNIFILE *u = (UNIFILE *)fc->index;
if (fc->fs != &uni_filesys) {
ALERT("ERROR: wrong file system getxattr called");
return EINTRN;
}
xattr->index = fc->index;
xattr->dev = fc->dev;
xattr->nlink = 1;
xattr->blksize = 1;
/* If "u" is null, then we have the root directory, otherwise
* we use the UNIFILE structure to get the info about it
*/
if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) {
xattr->uid = xattr->gid = 0;
xattr->size = xattr->nblocks = 0;
xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
xattr->attr = FA_DIR;
} else {
xattr->uid = u->dev;
xattr->gid = 0;
xattr->size = xattr->nblocks = strlen(u->data) + 1;
xattr->mode = u->mode;
xattr->attr = 0;
}
xattr->mtime = xattr->atime = xattr->ctime = 0;
xattr->mdate = xattr->adate = xattr->cdate = 0;
return 0;
}
static long ARGS_ON_STACK
uni_chattr(dir, attrib)
fcookie *dir;
int attrib;
{
UNUSED(dir); UNUSED(attrib);
return EACCDN;
}
static long ARGS_ON_STACK
uni_chown(dir, uid, gid)
fcookie *dir;
int uid, gid;
{
UNUSED(dir); UNUSED(uid);
UNUSED(gid);
return EINVFN;
}
static long ARGS_ON_STACK
uni_chmode(dir, mode)
fcookie *dir;
unsigned mode;
{
UNUSED(dir);
UNUSED(mode);
return EINVFN;
}
static long ARGS_ON_STACK
uni_rmdir(dir, name)
fcookie *dir;
const char *name;
{
long r;
r = uni_remove(dir, name);
if (r == EFILNF) r = EPTHNF;
return r;
}
static long ARGS_ON_STACK
uni_remove(dir, name)
fcookie *dir;
const char *name;
{
UNIFILE *u, *lastu;
UNUSED(dir);
lastu = 0;
u = u_root;
while (u) {
if (!strncmp(u->name, name, NAME_MAX)) {
if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF;
kfree(u->data);
if (lastu)
lastu->next = u->next;
else
u_root = u->next;
kfree(u);
return 0;
}
lastu = u;
u = u->next;
}
return EFILNF;
}
static long ARGS_ON_STACK
uni_getname(root, dir, pathname, size)
fcookie *root, *dir; char *pathname;
int size;
{
FILESYS *fs;
UNIFILE *u;
char *n;
fcookie relto;
char tmppath[PATH_MAX];
long r;
UNUSED(root);
if (size <= 0) return ERANGE;
fs = dir->fs;
if (dir->dev == UNIDRV) {
*pathname = 0;
return 0;
}
for (u = u_root; u; u = u->next) {
if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) {
*pathname++ = '\\';
if (--size <= 0) return ERANGE;
for (n = u->name; *n; ) {
*pathname++ = *n++;
if (--size <= 0) return ERANGE;
}
break;
}
}
if (!u) {
ALERT("unifs: couldn't match a drive with a directory");
return EPTHNF;
}
if (dir->dev >= NUM_DRIVES) {
if ((*fs->root)(dir->dev, &relto) == 0) {
if (!(fs->fsflags & FS_LONGPATH)) {
r = (*fs->getname)(&relto, dir, tmppath, PATH_MAX);
release_cookie(&relto);
if (r) {
return r;
}
if (strlen(tmppath) < size) {
strcpy(pathname, tmppath);
return 0;
} else {
return ERANGE;
}
}
r = (*fs->getname)(&relto, dir, pathname, size);
release_cookie(&relto);
return r;
} else {
*pathname = 0;
return EINTRN;
}
}